package otherPractice;

/**
 * 身份证生成器
 *    生成逻辑：
 *      根据《中华人民共和国国家标准GB 11643-1999》中有关公民身份号码的规定，
 *      公民身份号码是特征组合码，由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为：
 *      六位数字地址码，八位数字出生日期码，三位数字顺序码和一位数字校验码。顺序码的奇数分给男性，
 *      偶数分给女性。校验码是根据前面十七位数字码，按照ISO 7064:1983.MOD 11-2校验码计算出来
 *      的检验码。
 *      1. 前1-6位数字表示：所在省（直辖市、自治区）、市、县的代码；
 *      2. 第7—14位数字表示：出生年、月、日；
 *      3. 第15、16位数字表示：所在地的派出所的代码；
 *      4. 第17位数字表示性别：奇数表示男性，偶数表示女性；
 *      5. 最后一位是校验码，校验你的身份证号码是否合格；
 *
 *      ===  算法逻辑  ====
 *      两个必要因素：加权因子(wi) | 校验编码
 *      wi：7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
 *      校验编码：1 0 x 9 8 7 6 5 4 3 2
 *      公式：S =
 *      通俗理解就是：身份证的第一位*加权因子的第一位 + 身份证的第二位*加权因子的第二位
 *      ...  以此类推。
 *
 *      求出的和 % 11，得到一个校验位码 （假设是：5）
 *      最后通过校验位码从校验编码中取出校验码（校验编码中的第5个数）
 *      得到的数字与身份证最后一位匹配，如果相同，那就是合格的身份证号码
 *      （第5位是8，那么身份证位数也必须是8）
 *
 */
public class IdentityCardGenerateUtill {


    static Integer[] weightArr = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
    static String[] checkCode = {"1", "0", "x", "9", "8", "7", "6", "5", "4", "3", "2"};

    public String getCheckCode(String cardNum){
        if("".equals(cardNum) || cardNum.length() < 17){
            return null;
        }
        String[] numArr = cardNum.split("");
        Integer sum = 0;
        for(int i = 0; i < 17; i++){
            sum = sum + Integer.valueOf(numArr[i]) * weightArr[i];
        }

        Integer codeIndex = sum%11;
        String ressult = checkCode[codeIndex];

        return ressult;
    }

    public boolean checkIdentityCode(String cardNum){
        String lastNum = cardNum.substring(cardNum.length()-1);
        String checkCode = getCheckCode(cardNum);
        if(lastNum.equals(checkCode)){
            return true;
        }else {
            return false;
        }
    }


    public static void main(String[] args) {
        String cardNum = "411424199112186673";
        IdentityCardGenerateUtill utill = new IdentityCardGenerateUtill();
        String code = utill.getCheckCode(cardNum);
        System.out.println("-----   code=  " + code);
        boolean flag = utill.checkIdentityCode(cardNum);
        System.out.println("---- flag =  " + flag);
    }

}
